package org.dev.vlp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dev.vlp.constants.EnumNotificationCategory;
import org.dev.vlp.constants.EnumNotificationType;
import org.dev.vlp.dto.LikeContent;
import org.dev.vlp.entity.Comment;
import org.dev.vlp.entity.Moment;
import org.dev.vlp.entity.Notification;
import org.dev.vlp.entity.User;
import org.dev.vlp.mapper.CommentMapper;
import org.dev.vlp.mapper.MomentMapper;
import org.dev.vlp.mapper.UserMapper;
import org.dev.vlp.service.NotificationService;
import org.dev.vlp.mapper.NotificationMapper;
import org.dev.vlp.utils.BeanCopyUtils;
import org.dev.vlp.utils.PageResult;
import org.dev.vlp.utils.PageUtils;
import org.dev.vlp.vo.AtNotificationVo;
import org.dev.vlp.vo.CommentNotificationVo;
import org.dev.vlp.vo.MomentVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author 86184
* @description 针对表【vlp_notification(通知表)】的数据库操作Service实现
* @createDate 2023-01-13 13:12:44
*/
@Service
public class NotificationServiceImpl extends ServiceImpl<NotificationMapper, Notification>
    implements NotificationService{

    @Autowired
    private NotificationMapper notificationMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MomentMapper momentMapper;

    @Autowired
    private CommentMapper commentMapper;


    @Override
    public void sendNotification(Notification notification,long userId) {

        EnumNotificationType type = EnumNotificationType.value2enum.get(notification.getType());
        notification.setSendUserId((long)userId);
        notification.setCategory(type.getCategory());
        notificationMapper.insert(notification);

        // 评论
        if (Objects.equals(type.getCategory(), EnumNotificationCategory.COMMENT.getValue())) {
            userMapper.updateCommentUnread((long) userId, 1);
        }

        // @我
        if (Objects.equals(type.getCategory(), EnumNotificationCategory.AT.getValue())) {
            userMapper.updateAtUnread((long) userId, 1);
        }

        // 通知
        if (Objects.equals(type.getCategory(), EnumNotificationCategory.NOTIFICATION.getValue())) {
            userMapper.updateNotificationUnread((long) userId,1);
        }
    }

    @Override
    public PageResult queryAtInfo(int page, int size,long userId) {
        int start = PageUtils.getStart(page, size);
        QueryWrapper<Notification> notificationQueryWrapper = new QueryWrapper<>();
        notificationQueryWrapper.eq("receive_user_id",userId)
                .eq("category",EnumNotificationCategory.AT.getValue())
                .orderByDesc("gmt_create")
                .last("limit "+String.valueOf(start)+","+String.valueOf(size));
        List<Notification> dboList = notificationMapper.selectList(notificationQueryWrapper);
        Long aLong = notificationMapper.selectCount(notificationQueryWrapper);
        if (CollectionUtils.isEmpty(dboList)) {
            return new PageResult(dboList,aLong,size);
        }

        // 查询发消息的用户
        Set<Long> sendUserIdSet = dboList.stream().map(Notification::getSendUserId).collect(Collectors.toSet());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("user_id",new ArrayList<>(sendUserIdSet)).eq("is_deleted",0);
        List<User> sendUserDBOList = userMapper.selectList(userQueryWrapper);
        Map<Long, User> idToUser = sendUserDBOList.stream().collect(Collectors.toMap(User::getUserId, Function.identity(), (key1, key2) -> key2));

        // 查询动态
        Set<Long> momentIdSet = dboList.stream().map(Notification::getMomentId).collect(Collectors.toSet());
        QueryWrapper<Moment> momentQueryWrapper = new QueryWrapper<>();
        momentQueryWrapper.eq("is_deleted",0).in("moment_id",new ArrayList<>(momentIdSet));
        List<Moment> momentList = momentMapper.selectList(momentQueryWrapper);
        List<MomentVo> momentDTOList=BeanCopyUtils.copy(momentList, MomentVo.class);
        Map<Long, MomentVo> idToMoment = momentDTOList.stream().collect(Collectors.toMap(MomentVo::getMomentId, Function.identity(), (key1, key2) -> key2));

        // 查询评论
        Set<Long> commentIdSet = dboList.stream().map(Notification::getCommentId).collect(Collectors.toSet());
        List<Comment> commentDBOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(commentIdSet)) {
            QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
            commentQueryWrapper.eq("is_deleted",0).in("comment_id",new ArrayList<>(commentIdSet));
            commentDBOList = commentMapper.selectList(commentQueryWrapper);
        }
        Map<Long, Comment> idToComment = commentDBOList.stream().collect(Collectors.toMap(Comment::getCommentId, Function.identity(), (key1, key2) -> key2));

        List<AtNotificationVo> dtoList = BeanCopyUtils.copy(dboList, AtNotificationVo.class);
        dtoList.forEach(notification -> {
            if (Objects.equals(notification.getType(), EnumNotificationType.REPOST.getValue())
                    || Objects.equals(notification.getType(), EnumNotificationType.AT_ON_MOMENT.getValue())) {
                notification.setMoment(idToMoment.get(notification.getMomentId()));
            }
            if (Objects.equals(notification.getType(), EnumNotificationType.AT_ON_COMMENT.getValue())
                    || Objects.equals(notification.getType(), EnumNotificationType.AT_ON_CHILDREN_COMMENT.getValue())) {
                MomentVo momentDTO = new MomentVo();
                momentDTO.setRepostedMoment(idToMoment.get(notification.getMomentId()));
                momentDTO.setGmtCreateTime(notification.getGmtCreate());

                User sendUserDBO = idToUser.get(notification.getSendUserId());
                momentDTO.setUserId(sendUserDBO.getUserId());
                momentDTO.setUsername(sendUserDBO.getUsername());
                momentDTO.setAvatar(sendUserDBO.getAvatar());

                Comment commentDBO = idToComment.get(notification.getCommentId());
                momentDTO.setContent(commentDBO.getContent());

                notification.setMoment(momentDTO);
            }
        });
        userMapper.clearAtUnread((long) userId);
        return new PageResult(dtoList,aLong,size);
    }

    @Override
    public PageResult queryLikeInfo(long userId,int page,int size) {
        int start = PageUtils.getStart(page, size);
        List<LikeContent> likeComment = notificationMapper.selectLike((int) userId,start,size);
        int aLong = notificationMapper.likeCount((int) userId);

        Set<Integer> sendUserIdSet = new HashSet<Integer>();
        Set<Integer> commentIdSet = new HashSet<Integer>();
        Set<Integer> momentIdSet = new HashSet<Integer>();
        likeComment.forEach(comment -> {
            Set<Integer> ids = new HashSet<Integer>();
            String concat = comment.getConcat();
            String[] split = concat.split(",");
            for(String s:split){
                sendUserIdSet.add(Integer.parseInt(s));
                ids.add(Integer.parseInt(s));
            }
            comment.setSentUserIds(ids);
            comment.setConcat(null);
            if(Objects.equals(comment.getType(), EnumNotificationType.LIKE_COMMENT.getValue())){
                commentIdSet.add(comment.getCommentId());
            }else{
                momentIdSet.add(comment.getMomentId());
            }
        });

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("user_id",new ArrayList<>(sendUserIdSet)).eq("is_deleted",0);
        List<User> sendUserDBOList = userMapper.selectList(userQueryWrapper);
        Map<Long, User> idToUser = sendUserDBOList.stream().collect(Collectors.toMap(User::getUserId, Function.identity(), (key1, key2) -> key2));

        // 查询动态
        List<Moment> momentList= new ArrayList<>();
        if(!CollectionUtils.isEmpty(momentIdSet)){
            QueryWrapper<Moment> momentQueryWrapper = new QueryWrapper<>();
            momentQueryWrapper.eq("is_deleted",0).in("moment_id",new ArrayList<>(momentIdSet));
            momentList = momentMapper.selectList(momentQueryWrapper);
        }
        Map<Long, Moment> idToMoment = momentList.stream().collect(Collectors.toMap(Moment::getMomentId, Function.identity(), (key1, key2) -> key2));
        // 查询评论
        List<Comment> commentDBOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(commentIdSet)) {
            QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
            commentQueryWrapper.eq("is_deleted",0).in("comment_id",new ArrayList<>(commentIdSet));
            commentDBOList = commentMapper.selectList(commentQueryWrapper);
        }
        Map<Long, Comment> idToComment = commentDBOList.stream().collect(Collectors.toMap(Comment::getCommentId, Function.identity(), (key1, key2) -> key2));

        likeComment.forEach(notification -> {
            Set<User> sendUsers = new HashSet<User>();
            for (int s : notification.getSentUserIds()) {
                User user = idToUser.get((long) s);
                sendUsers.add(user);
            }
            notification.setSentUsers(sendUsers);
//            notification.setSentUserIds(null);
            if(Objects.equals(notification.getType(), EnumNotificationType.LIKE_COMMENT.getValue())){
                Comment comment = idToComment.get((long)notification.getCommentId());
//                System.out.println(notification.getCommentId());
                notification.setCommentContent(comment.getContent());
                notification.setMomentId(null);
            }else{
                Moment comment = idToMoment.get((long)notification.getMomentId());
//                System.out.println(notification.getMomentId());
                notification.setMomentContent(comment.getContent());
                notification.setCommentId(null);
            }
        });
        userMapper.clearNotificationUnread((long) userId);
        return new PageResult(likeComment,(long)aLong,size);
    }

    @Override
    public void clearNotificationCount(EnumNotificationCategory category,long userId) {

        if (Objects.equals(category, EnumNotificationCategory.COMMENT)) {
            userMapper.clearCommentUnread((long) userId);
        }
        if (Objects.equals(category, EnumNotificationCategory.AT)) {
            userMapper.clearAtUnread((long) userId);
        }
        if (Objects.equals(category, EnumNotificationCategory.NOTIFICATION)) {
            userMapper.clearNotificationUnread((long) userId);
        }
    }

    @Override
    public PageResult queryCommentInfo(int page, int size,long userId) {

        int start = PageUtils.getStart(page, size);
        QueryWrapper<Notification> notificationQueryWrapper = new QueryWrapper<>();
        notificationQueryWrapper.eq("receive_user_id",userId)
                .eq("category",EnumNotificationCategory.COMMENT.getValue())
                .eq("is_deleted",0)
                .orderByDesc("gmt_create")
                .last("limit "+String.valueOf(start)+","+String.valueOf(size));
        List<Notification> dboList = notificationMapper.selectList(notificationQueryWrapper);
        Long aLong = notificationMapper.selectCount(notificationQueryWrapper);
        if (CollectionUtils.isEmpty(dboList)) {
            return new PageResult(dboList,aLong,size);
        }

        // 查询发消息的用户
        Set<Long> sendUserIdSet = dboList.stream().map(Notification::getSendUserId).collect(Collectors.toSet());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("user_id",new ArrayList<>(sendUserIdSet)).eq("is_deleted",0);
        List<User> sendUserDBOList = userMapper.selectList(userQueryWrapper);
        Map<Long, User> idToUser = sendUserDBOList.stream().collect(Collectors.toMap(User::getUserId, Function.identity(), (key1, key2) -> key2));

        // 查询动态
        Set<Long> momentIdSet = dboList.stream().map(Notification::getMomentId).collect(Collectors.toSet());
        QueryWrapper<Moment> momentQueryWrapper = new QueryWrapper<>();
        momentQueryWrapper.eq("is_deleted",0).in("moment_id",new ArrayList<>(momentIdSet));
        List<Moment> momentList = momentMapper.selectList(momentQueryWrapper);
        List<MomentVo> momentDTOList=BeanCopyUtils.copy(momentList, MomentVo.class);
        Map<Long, MomentVo> idToMoment = momentDTOList.stream().collect(Collectors.toMap(MomentVo::getMomentId, Function.identity(), (key1, key2) -> key2));

        // 查询评论
        Set<Long> commentIdSet = dboList.stream().map(Notification::getCommentId).collect(Collectors.toSet());
        commentIdSet.addAll(dboList.stream().map(Notification::getParentCommentId).collect(Collectors.toSet()));
        List<Comment> commentDBOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(commentIdSet)) {
            QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
            commentQueryWrapper.eq("is_deleted",0).in("comment_id",new ArrayList<>(commentIdSet));
            commentDBOList = commentMapper.selectList(commentQueryWrapper);
        }
        Map<Long, Comment> idToComment = commentDBOList.stream().collect(Collectors.toMap(Comment::getCommentId, Function.identity(), (key1, key2) -> key2));

        List<CommentNotificationVo> dtoList = BeanCopyUtils.copy(dboList, CommentNotificationVo.class);
        dtoList.forEach(notification -> {
            if (Objects.equals(notification.getType(), EnumNotificationType.COMMENT_TO_MOMENT.getValue())) {
                MomentVo momentDTO = new MomentVo();
                momentDTO.setRepostedMoment(idToMoment.get(notification.getMomentId()));
                momentDTO.setGmtCreateTime(notification.getGmtCreate());

                User sendUserDBO = idToUser.get(notification.getSendUserId());
                momentDTO.setUserId(sendUserDBO.getUserId());
                momentDTO.setUsername(sendUserDBO.getUsername());
                momentDTO.setAvatar(sendUserDBO.getAvatar());

                Comment commentDBO = idToComment.get(notification.getCommentId());
                momentDTO.setContent(commentDBO.getContent());

                notification.setMoment(momentDTO);
            }

            if (Objects.equals(notification.getType(), EnumNotificationType.REPLY_TO_MOMENT_COMMENT.getValue())) {
                Comment commentDBO = idToComment.get(notification.getCommentId());
                Comment parentCommentDBO = idToComment.get(notification.getParentCommentId());
                User userDBO = idToUser.get(notification.getSendUserId());

                notification.setSendUserName(userDBO.getUsername());
                notification.setSendUserAvatarUrl(userDBO.getAvatar());
                notification.setCommentContent(commentDBO.getContent());
                notification.setParentCommentContent(parentCommentDBO.getContent());
            }
        });
        userMapper.clearCommentUnread((long) userId);
        return new PageResult(dtoList,aLong,size);
    }
}




